package com.tianhao.luo.lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 定制化线程间通信
 * @author tianhao.luo@hand-china.com
 */
public class ThreadNotifyDemo2 {


    public static void main(String[] args) {
        ShareResource shareResource = new ShareResource();

        new Thread(()->{
            for (int i = 0; i <= 10; i++) {
                try {
                    shareResource.print5(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"aa").start();

        new Thread(()->{
            for (int i = 0; i <= 10; i++) {
                try {
                    shareResource.print10(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"bb").start();


        new Thread(()->{
            for (int i = 0; i <= 10; i++) {
                try {
                    shareResource.print15(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"cc").start();

    }

    static class ShareResource{
        // 定义标志位
        private int flag = 1;

        // 创建lock锁
        private Lock lock = new ReentrantLock();

        // 创建三个condition
        private Condition c1 = lock.newCondition();
        private Condition c2 = lock.newCondition();
        private Condition c3 = lock.newCondition();

        /**
         * 打印5次，参数第几轮
         */
        public void print5(int loop) throws InterruptedException{
            lock.lock();
            try {
                // 判断
                while (flag != 1){
                    c1.await();
                }
                for (int i = 1; i < 6; i++) {
                    System.out.println(Thread.currentThread().getName()+"::"+i+",第"+loop+"轮");
                }
                // 通知指定的bb线程，先修改flag再去唤醒c2
                flag = 2;
                c2.signal();
            }finally {
                lock.unlock();
            }
        }



        /**
         * 打印10次，参数第几轮
         */
        public void print10(int loop) throws InterruptedException{
            lock.lock();
            try {
                // 判断
                while (flag != 2){
                    c2.await();
                }
                for (int i = 1; i < 11; i++) {
                    System.out.println(Thread.currentThread().getName()+"::"+i+",第"+loop+"轮");
                }
                // 通知指定的bb线程，先修改flag再去唤醒c3
                flag = 3;
                c3.signal();
            }finally {
                lock.unlock();
            }
        }


        /**
         * 打印15次，参数第几轮
         */
        public void print15(int loop) throws InterruptedException{
            lock.lock();
            try {
                // 判断
                while (flag != 3){
                    c3.await();
                }
                for (int i = 1; i < 16; i++) {
                    System.out.println(Thread.currentThread().getName()+"::"+i+",第"+loop+"轮");
                }
                // 通知指定的bb线程，先修改flag再去唤醒c1
                flag = 1;
                c1.signal();
            }finally {
                lock.unlock();
            }
        }
    }
}
